#!/usr/bin/env bash
#set -x

appnodes="01 02 05 06"
lispnodes="04 08"
nodes="$appnodes $lispnodes"

# -----------------------------------------------------------------------------

addbridge() {
    ip link add name b0 type bridge
    ip link set b0 up
    ip link set eth0 master b0
    ip addr del $IP dev eth0
    ip addr del $IP6 dev eth0
    ip addr add $IP dev b0
    ip addr add $IP6 dev b0
    ip route add default via $GW
}

delbridge() {
    ip link delete b0 type bridge
    ip addr add $IP/16 dev eth0
    ip route add default via 172.17.42.1
}

internetnode() {
    local n="$1"
    local x=$((10#$n))

    ip link add netns node$n c0 address 00:00:00:00:cc:$n type veth \
        peer name lisp$n address 00:00:00:00:dd:$n
    ip netns exec node$n ip link set c0 up
    ip link set lisp$n up

    ip netns exec node$n ip addr add 172.17.1.$x/16 dev c0
    ip netns exec node$n ip route add default via $IP
    ip link set lisp$n master b0
}

addinternet() {
    for n in $lispnodes; do
        internetnode $n
    done
}

# -----------------------------------------------------------------------------

bringup() {

ip netns add r2
ip netns exec r2 sysctl -wq net.ipv6.conf.all.forwarding=1
ip netns exec r2 sysctl -wq net.ipv4.ip_forward=1

appnode() {
    local n="$1"
    local x=$((10#$n))
    ip netns add node$n

    # link
    ip link add netns node$n e0 address 00:00:00:00:01:$n type veth \
        peer name e$n netns r2 address 00:00:00:00:00:$n
    ip netns exec node$n ip link set e0 up
    ip netns exec r2     ip link set e$n up

    # ipv6
    ip netns exec r2     ip addr add fd80:$n::1/56 dev e$n
    ip netns exec node$n ip addr add fd80:$n::2/56 dev e0
    ip netns exec node$n ip -6 route add default via fd80:$n::1 dev e0
}

intelnode() {
    local n="$1"
    local pci0="$2"
    local e0="$3"
    local pcin="$4"
    local en="$5"
    ip netns add node$n
    echo -n $pci0 > /sys/bus/pci/drivers/ixgbe/unbind # e0
    echo -n $pcin > /sys/bus/pci/drivers/ixgbe/bind   # e$n
    ip link set $en netns r2
    ip netns exec r2 ip link add link $en name $en.2 type vlan id 2
    ip netns exec r2 ip link set dev $en.2 address 00:00:00:00:00:$n
    ip netns exec r2 ip addr add fd80:$n::1/56 dev $en.2
    ip netns exec r2 ip link set $en up
    ip netns exec r2 ip link set $en.2 up
}

if [ "$intel1" ]; then
    ln -sf lisper04.conf.intel10g lisper04.conf
    ln -sf lisper08.conf.intel10g lisper08.conf
    for n in $appnodes; do
        appnode $n
    done
    intelnode 04 $intel1_pci $intel1 $intel2_pci $intel2
    intelnode 08 $intel3_pci $intel3 $intel4_pci $intel4
else
    ln -sf lisper04.conf.veth lisper04.conf
    ln -sf lisper08.conf.veth lisper08.conf
    for n in $nodes; do
        appnode $n
    done
fi

eth() {
local p="$1"
local n="$2"
ip link add netns node$p e$n address 00:00:00:00:01:$n type veth \
   peer name t$n netns node$p address 00:00:00:00:aa:$n
ip netns exec node$p ip addr add 10.0.0.$n/24 dev t$n
ip netns exec node$p ip link set e$n up
ip netns exec node$p ip link set t$n up
}
eth 04 03
eth 04 13
eth 08 07
eth 08 17

for n in $appnodes; do
    ip netns exec node$n ip tuntap add dev t0 mode tap
    ip netns exec node$n ip link set address 00:00:00:00:aa:$n dev t0
    ip netns exec node$n ifconfig t0 10.0.0.$n/24 mtu 1400 up
    ./l2tp.app$n start
done

for n in $lispnodes; do
    ./lisp$n start
    ./lisper$n start
done
}

teardown() {
for n in $appnodes; do
    ./l2tp.app$n stop
done

for n in $lispnodes; do
    ./lisp$n stop
    ./lisper$n stop
    rm -f lisper$n.conf
done

for n in $nodes; do
    ip netns del node$n
done

ip netns del r2
}

if [ "$1" ]; then $@; else echo "Usage: $0 <command>"; fi
